Vue3.0 实现 word 文档的预览和下载 您所在的位置:网站首页 vue预览word excel 内网 Vue3.0 实现 word 文档的预览和下载

Vue3.0 实现 word 文档的预览和下载

2023-04-26 11:07| 来源: 网络整理| 查看: 265

需求

项目前端使用vue3.0 + Element Plus搭建,要求纯前端实现word文档的预览和下载功能。废话不多说,开干。

效果展示 先给大家录个屏,方便看效果:

word20230421_063000-min.gif

把下载下来的word文档打开后就是这样:

image.png

用到的插件: docxtemplater pizzip file-saver docxtemplater-image-module-free angular-expressions: lodash docx-preview 实现思路: 创建模板文件,必须是docx的格式;

image.png

在vue3.0项目中把准备好的模板文件,放到项目的public文件夹下,等待调用;

image.png

开始构建环境,上代码; 基础模块 # @/utils/exportFile // 引入基本模块 import Docxtemplater from "docxtemplater"; import PizZip from "pizzip"; import PizZipUtils from "pizzip/utils/index.js"; import { saveAs } from "file-saver"; // 图片模块 import ImageModule from "docxtemplater-image-module-free"; // 解析语法模块 import expressions from "angular-expressions"; import assign from "lodash/assign"; // 文档预览模块 import { renderAsync } from "docx-preview"; expressions.filters.lower = function (input) { if (!input) return input; return input.toLowerCase(); }; function angularParser(tag) { tag = tag .replace(/^\.$/, "this") .replace(/('|')/g, "'") .replace(/("|")/g, '"'); const expr = expressions.compile(tag); return { get: function (scope, context) { let obj = {}; const scopeList = context.scopeList; const num = context.num; for (let i = 0, len = num + 1; i < len; i++) { obj = assign(obj, scopeList[i]); } return expr(scope, obj); }, }; } // 加载文件 function loadFile(url, callback) { PizZipUtils.getBinaryContent(url, callback); } // 配置空值替换函数 作为配置参数可配置在setOptions中 function nullGetter(part, scopeManager) { if (!part.module) { return "-null-"; } if (part.module === "rawxml") { return ""; } return "--"; } 复制代码 预览的实现思路 # @/utils/exportFile /** * 预览word,支持图片 * @param {Object} tempDocxPath 模板文件路径 * @param {Object} wordData 导出数据 * @param {Object} fileName 导出文件名 * @param {Arrsy} imgSize 自定义图片尺寸 */ export const getWordImage = (tempDocxPath, wordData, imgSize, file) => { // 本地word.docx文件需要放在public目录下 loadFile(tempDocxPath, (error, content) => { if (error) { throw error; } // 图片配置 const imageOpts = { getImage: function (tagValue, tagName) { return new Promise(function (resolve, reject) { PizZipUtils.getBinaryContent(tagValue, function (error, content) { if (error) { return reject(error); } return resolve(content); }); }); }, getSize: function (img, tagValue, tagName) { const size = imgSize[tagName] ? imgSize[tagName] : [150, 150] return size; }, }; let imageModule = new ImageModule(imageOpts); const zip = new PizZip(content); // 实例化有两种方式 这里是链式 const doc = new Docxtemplater() .loadZip(zip) .setOptions({ // delimiters: { start: "[[", end: "]]" }, paragraphLoop: true, linebreaks: true, nullGetter: nullGetter, parser: angularParser, }) .attachModule(imageModule) .compile(); doc.renderAsync(wordData).then(() => { const out = doc.getZip().generate({ type: "blob", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", }); renderAsync(out, file); }); }); } 复制代码 下载的实现思路 # @/utils/exportFile /** * 导出word,不支持图片 * @param {Object} tempDocxPath 模板文件路径 * @param {Object} wordData 导出数据 * @param {Object} fileName 导出文件名 */ export const exportWord = (tempDocxPath, wordData, fileName) => { // 本地word.docx文件需要放在public目录下 loadFile(tempDocxPath, (error, content) => { if (error) { throw error; } const zip = new PizZip(content); // 没有配置解析语法,深层次对象语法(obj.xx.xx)不可识别 const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, }); doc.render(wordData); const out = doc.getZip().generate({ type: "blob", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", }); // Output the document using Data-URI saveAs(out, `${fileName}.docx`); }); } /** * 导出word,支持图片 * @param {Object} tempDocxPath 模板文件路径 * @param {Object} wordData 导出数据 * @param {Object} fileName 导出文件名 * @param {Arrsy} imgSize 自定义图片尺寸 */ export const exportWordImage = (tempDocxPath, wordData, fileName, imgSize) => { // 本地word.docx文件需要放在public目录下 loadFile(tempDocxPath, (error, content) => { if (error) { throw error; } // 图片配置 const imageOpts = { getImage: function (tagValue, tagName) { return new Promise(function (resolve, reject) { PizZipUtils.getBinaryContent(tagValue, function (error, content) { if (error) { return reject(error); } return resolve(content); }); }); }, getSize: function (img, tagValue, tagName) { const size = imgSize[tagName] ? imgSize[tagName] : [150, 150] return size; }, }; let imageModule = new ImageModule(imageOpts); const zip = new PizZip(content); // 实例化有两种方式 这里是链式 const doc = new Docxtemplater() .loadZip(zip) .setOptions({ // delimiters: { start: "[[", end: "]]" }, paragraphLoop: true, linebreaks: true, nullGetter: nullGetter, parser: angularParser, }) .attachModule(imageModule) .compile(); doc.renderAsync(wordData).then(function () { const out = doc.getZip().generate({ type: "blob", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", }); saveAs(out, `${fileName}.docx`); }); }); } 复制代码 开始使用 # CreateWordDocx.vue 下载启动方案 预览启动方案 import { exportWordImage, getWordImage } from "@/utils/exportFile"; export default { name: "CreateWordDocx", data() { return { dialogVisible: false, htmlTitle: "启动方案", imgSize: { imgPath: [150, 150], imgPath1: [550, 250], }, startSchemeTemplate: { name: "XXXXXXX启动调度实施方案", time: "2023.4.20", scope: `1.XXXX所有一、二次设备 2.XXXX主变、XXXX主变(XX管辖)`, projectAdjuster: `1.XXXX,XXXX主变冲击五次、核相。 2.XXXXX设备冲击一次,XXXXXXX二次定相。 3.XXXXXX,XXXX差动保护带负荷试验。(XX管辖) 4.XXXXXX备自投实跳试验。`, condition: `1.XXX启动范围内的所有一、二次设备施工结束,验收合格,监控信息与相应调控人员核对完备,设备可以带电,站内一次设备相位正确。 2.XXX待用XXXXXX、待用XXXXXX、待用XXXXXX、待用XXXXXX、待用XXXXXX、待用XXXXXX、待用XXXXXX、银标XXXXXX、银阳XXXXXX、银区XXXXXX、待用XXXXXX、待用XXXXXX、待用XXXXXX、XXXXXX开关保护按定值单整定并投入。 3.启动范围内所有设备均为冷备用状态。`, stepAdjuster: `1.XXXXXX冲击一次、定相。 2.XXXXXX一次设备冲击(见附图2)`, imgPath: "https://docxtemplater.com/puffin.png", }, }; }, methods: { downLoad() { exportWordImage( "../template.docx", this.startSchemeTemplate, this.htmlTitle, this.imgSize ); }, goPreview() { this.dialogVisible = true; }, handleOpened() { getWordImage( "../template.docx", this.startSchemeTemplate, this.imgSize, this.$refs.file ); }, }, }; .btn { float: left; margin: 0 0 24px; } .docWrap { height: 700px; overflow: auto; clear: both; } 复制代码 参考文章 * [wordDown](https://github.com/H-newborn/wordDown) * [vue中使用docx-preview插件预览word文档](https://zhuanlan.zhihu.com/p/437059185) 复制代码 备注

源码已上传gitee,功能已集成至项目:VUE-ADMIN-MS,大家自行取用,记得给 Star 哦 !!!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有